<script lang="jsx">
import { defineComponent, unref, toRef, ref, computed } from 'vue'
import GridQuery from './query.vue'
import { isNullOrUnDef } from '@/utils/is'
import { doSliderChange, doSelectChange, enumRemoteMethod, loadTreeSelectData } from './tool'
import { inputQuerySearch } from '../utils/table.ts'
import TextShow from '@/components/TextShow/index.vue'
// import MetaUpload from '@/modules/meta/Upload.vue'
import CascaderSelect from '@/modules/meta/CascaderSelect.vue'
import { infiniteScroll } from '@/modules/utils/directives'
import TreeSelect from '@/modules/meta/TreeSelect.vue'
import TreeSelectMultiple from '@/modules/meta/TreeSelectMultiple.vue'
import PageSelect from '@/modules/meta/PageSelect.vue'

export default defineComponent({
  name: 'GridQuery',
  directives: {
    infiniteScroll
  },
  props: {
    // 传递共用form数据
    model: {
      type: Object || undefined,
      default: undefined
    },
    // 父级grid的配置属性 { type, style, class, value }, type: tabs/collapse
    page: {
      type: Object,
      default: () => ({})
    },
    // grid配置
    grid: {
      type: Array,
      default: () => []
    },
    // 传递共用fields字段配置
    fields: {
      type: Array,
      default: () => []
    },
    // 传递共用operators操作配置
    operators: {
      type: Array,
      default: () => []
    },
    // 字典数据
    datas: {
      type: Object,
      default: () => ({})
    },
    emitFun: {
      type: Function
    }
  },
  setup(props) {
    const page = unref(props.page || {})
    const grids = unref(props.grid || [])
    const fields = unref(props.fields || [])
    const operators = unref(props.operators || [])
    const datas = unref(props.datas || [])
    const model = ref(props.model)
    const type = unref(page.type)
    const emit = props.emitFun

    // 执行按钮操作，第三个参数command配置dropdown，替换targets参数
    const doOperator = async (form, op, command) => {}

    // Form表单渲染
    const formRender = (row, col, grid) => {
      switch (col.type) {
        case 'string':
        case 'component':
          return col.pinyin_search || col.source ? (
            <el-autocomplete
              placeholder={col.placeholder || '请输入'}
              clearable={true}
              value-key="name"
              {...col.autocomplete}
              v-model={row[col.key]}
              fetch-suggestions={(qs, cb) => inputQuerySearch(qs, cb, col, row)}
            />
          ) : (
            <el-input
              placeholder={col.placeholder || '请输入'}
              clearable
              {...col.props}
              {...grid?.props}
              v-model={row[col.key]}
              onKeyup={(e) => {
                if (e.key === 'Enter') {
                  emit('search', col)
                }
              }}
            />
          )
        case 'text':
        case 'textarea':
          return (
            <el-input
              placeholder={col.placeholder || '请输入'}
              clearable
              rows={col.rows || 1}
              {...col.props}
              {...grid?.props}
              type="textarea"
              v-model={row[col.key]}
              onKeyup={(e) => {
                if (e.key === 'Enter') {
                  emit('search', col)
                }
              }}
            />
          )
        case 'number':
        case 'int':
        case 'float':
          return (
            <el-input
              placeholder={col.placeholder || '请输入'}
              {...col.props}
              {...grid?.props}
              type="number"
              v-model={row[col.key]}
              onKeyup={(e) => {
                if (e.key === 'Enter') {
                  emit('search', col)
                }
              }}
            />
          )
        case 'password':
          return (
            <el-input
              placeholder={col.placeholder || '请输入'}
              {...col.props}
              {...grid?.props}
              type="password"
              show-password
              v-model={row[col.key]}
            />
          )
        case 'bool':
        case 'checkbox':
          // return <el-checkbox {...col.props} {...grid?.props} v-model={row[col.key]} true-value={"1"} false-value={"0"} />;
          return <el-checkbox {...col.props} {...grid?.props} v-model={row[col.key]} />
        case 'enum':
          return <PageSelect v-model={row[col.key]} col={col} form={row} />
        case 'list':
          if (typeof row[col.key] === 'string' && /\[.+\]/.test(row[col.key])) {
            row[col.key] = JSON.parse(row[col.key])
          }
          return (
            <PageSelect
              v-model={row[col.key]}
              allow-create
              multiple
              collapse-tags
              col={col}
              form={row}
            />
          )
        case 'tree-select':
          return <TreeSelect v-model={row[col.key]} config={col.source} />
        case 'tree-select-multiple':
          return <TreeSelectMultiple v-model={row[col.key]} config={col.source} multiple />
        case 'range':
          return (
            <el-slider
              size="small"
              show-input
              show-input-controls={false}
              {...col.props}
              {...grid?.props}
              v-model={row[col.key]}
              step={col.step || 1}
              min={col.range[0]}
              max={
                col.maxField
                  ? computed(() =>
                      Math.min(
                        col.range[1],
                        ...[col.maxField]
                          .flat()
                          .map((f) =>
                            Number((Math.floor(8000 / col.step / row[f]) * col.step).toFixed(2))
                          )
                      )
                    ).value
                  : col.range[1]
              }
              {...(col.watch
                ? {
                    onChange: (val) => {
                      doSliderChange(row, col, 'change', val)
                    },
                    onInput: (val) => {
                      doSliderChange(row, col, 'input', val)
                    }
                  }
                : {})}
            />
          )
        case 'radio':
          return (
            <el-radio-group {...col.props} {...grid?.props} v-model={row[col.key]}>
              {(col.values || []).map((val) =>
                typeof val === 'object' ? (
                  <el-radio key={val.key} label={val.key}>
                    {val.name}
                  </el-radio>
                ) : (
                  <el-radio key={val} label={val}>
                    {val}
                  </el-radio>
                )
              )}
            </el-radio-group>
          )
        case 'date':
          return (
            <el-date-picker
              placeholder="选择日期"
              value-format="YYYY-MM-DD HH:mm:ss"
              type="date"
              {...col.props}
              {...grid?.props}
              v-model={row[col.key]}
            />
          )
        case 'datetime':
          return (
            <el-date-picker
              placeholder="选择日期时间"
              value-format="YYYY-MM-DD HH:mm:ss"
              type="datetime"
              {...col.props}
              {...grid?.props}
              v-model={row[col.key]}
            />
          )
        case 'cascader':
          return (
            <el-cascader
              clearable
              filterable
              placeholder="请选择"
              {...col.props}
              {...grid?.props}
              v-model={row[col.key]}
              options={col.values}
            />
          )
        case 'cascader-select':
          return (
            <CascaderSelect
              configs={col.configs}
              attrs={{ ...col.props, ...grid?.props }}
              model={row}
              checkStrictly={true}
            />
          )
        // case 'file':
        //   return <MetaUpload v-model={row[col.key]} meta={col} />
        default:
          return (
            <el-input
              placeholder={col.placeholder || '请输入'}
              clearable
              {...col.props}
              {...grid?.props}
              v-model={row[col.key]}
              onKeyup={(e) => {
                if (e.key === 'Enter') {
                  emit('search', col)
                }
              }}
            />
          )
      }
    }

    const operatorRender = (grid) => {
      const op = operators.find((op) => grid.operator === op.key)
      if (op && op.logo) {
        // 图标按钮
        return (
          <div
            class={`${model.value ? 'el-form-item' : ''} ${grid.class || ''}`}
            style={grid.style}
          >
            <el-button
              class="img-btn"
              title={op.name}
              {...op.props}
              {...grid?.props}
              onClick={() => doOperator(model.value, op)}
            >
              <img src={op.logo} />
            </el-button>
          </div>
        )
      } else if (op) {
        // 默认按钮
        return (
          <div
            class={`${model.value ? 'el-form-item' : ''} ${grid.class || ''}`}
            style={grid.style}
          >
            <el-button
              {...op.props}
              {...grid?.props}
              loading={!!op._loading}
              onClick={() => doOperator(model.value, op)}
            >
              {op.name}
            </el-button>
          </div>
        )
      } else {
        return
      }
    }

    // grid单元格渲染
    const renderGrid = (grid) => {
      // grid设置了visible:{field,value,exclude}判断值true才显示，配置exclude=true时，为隐藏
      const gridVisible = ref(
        grid.visible === false
          ? false
          : !grid.visible ||
              [grid.visible]
                .flat()
                .some(
                  (vis) =>
                    model.value &&
                    Object.keys(vis).every([vis[key]].flat().includes(model.value[key]))
                )
      )
      if (!gridVisible.value) {
        // return <div class={grid.class} style={grid.style}></div>
        return
      }
      // 如果有子grid，递归渲染
      if (grid.grid) {
        return (
          <div class={grid.class} style={grid.style}>
            <GridQuery
              page={grid}
              model={model}
              grid={grid.grid}
              fields={fields}
              operators={operators}
              datas={datas}
            ></GridQuery>
          </div>
        )
      }
      // form字段
      if (model.value && grid.field) {
        let field = fields.find((fd) => grid.field === fd.key)
        // 如果配置了一个meta里没有的字段，并且配了label，当input字段使用
        if (!field && grid.label) {
          field = {
            type: 'string',
            ...grid,
            key: grid.field
          }
        }
        if (field) {
          if (field.type === 'checkbox') {
            return (
              <div class={`el-form-item ${grid.class || ''}`} style={grid.style}>
                {formRender(model.value, field, grid)}
              </div>
            )
          }
          return (
            <el-form-item
              label={grid.label || field.name}
              prop={field.key}
              class={grid.class}
              style={grid.style}
            >
              {formRender(model.value, field, grid)}
            </el-form-item>
          )
        } else {
          return
        }
      }
      // 按钮
      if (grid.operator) {
        return operatorRender(grid)
      }
      // 其他内容作为text文本渲染
      return (
        <div class={`el-form-item ${grid.class || ''}`} style={grid.style}>
          {grid.text || grid.name}
        </div>
      )
    }

    // 组件交互布局
    if (type === 'tabs') {
      // tabs配置了field属性，作为tabs的切换值
      if (page.field) {
        if (isNullOrUnDef(model.value[page.field])) {
          model.value[page.field] = grids[0]?.value || 0
        }
        return () => (
          <el-tabs v-model={model.value[page.field]}>
            {grids.map((grid, idx) => (
              <el-tab-pane
                label={grid.title || idx + 1}
                name={isNullOrUnDef(grid.value) ? idx : grid.value}
              >
                {renderGrid(grid)}
              </el-tab-pane>
            ))}
          </el-tabs>
        )
      }
      // 未配置field使用下标index
      const activeTab = ref(0)
      return () => (
        <el-tabs v-model={activeTab.value}>
          {grids.map((grid, idx) => (
            <el-tab-pane label={grid.title || idx + 1} name={idx}>
              {renderGrid(grid)}
            </el-tab-pane>
          ))}
        </el-tabs>
      )
    } else if (type === 'collapse') {
      // 默认折叠，子grid配置visible:true展开
      const activeTab = ref(
        (grids || []).reduce((t, c, i) => {
          if (c.visible) t.push(i)
          return t
        }, [])
      )
      return () => (
        <el-collapse v-model={activeTab.value}>
          {grids.map((grid, idx) => (
            <el-collapse-item title={grid.title} name={idx}>
              {renderGrid(grid)}
            </el-collapse-item>
          ))}
        </el-collapse>
      )
    }
    return () => grids.map((grid) => renderGrid(grid))
  }
})
</script>
